#include <iostream>
#include <string>
#include <sstream>
#include <iterator>
#include <map>
#include <set>
#include <bitset>
#include <list>
#include <limits>
#include <vector>
#include <sstream>
#include <algorithm>
#include <numeric>
#include <functional>
#include <cstdlib>
#include <stdio.h>

#define _SKIP_LINE_ do{scanf("%*[^\n]"); getc(stdin);}while(0)
#define _COUNT_NON_ZERO_(x) \
(((((x)&~0UL/255*127)+~0UL/255*127|(x))&~0UL/255*128)/128%255)


using namespace std;
typedef pair<short, string>  Length_String;
typedef multimap<short, string> Hash;
typedef map<string, string> Dictionary;
typedef vector<short> AdjacencyList;
typedef pair<string, AdjacencyList> Node;
typedef vector<Node> Graph;


stringstream tokens(stringstream::in | stringstream::out);
Hash WordBySize;
Dictionary WordList;
vector<Graph> pre_computed(20);

const string no_output("No solution.");

Node Seq(const Length_String& p) {
	return make_pair(p.second, vector<short>());
}

char XOR (const char& i, const char& j) { return i^j; }

short HammingDistance(const string& lhs, const string& rhs) {
	short len = lhs.size();
	string res;
	transform(lhs.c_str(), lhs.c_str()+len, rhs.c_str(), back_inserter(res), XOR);
	const char* byte = res.c_str();
	const unsigned long* word  = (const unsigned long*) byte;
	short nWords = len/4;
	len = 0;
	while(nWords-- > 0) {
		len += _COUNT_NON_ZERO_(*word);
		word++;
	}
	return len;
}

pair<short,short> get_index(const Graph& graph, const string& source, const string& target) {
	short i=0, j=0;
	while((i < graph.size() || j < graph.size()) && (graph[i].first != source || graph[j].first != target)) {
		if(i < graph.size() && graph[i].first != source) ++i;	
		if(j < graph.size() && graph[j].first != target) ++j;	
	}
	return make_pair(i, j);
}

void init_graph(Graph& edit_graph, const string& start) {
	pair<Hash::const_iterator, Hash::const_iterator> range;
	range = WordBySize.equal_range(start.size());
	transform(range.first, range.second, back_inserter(edit_graph), Seq);
	Graph::iterator it = edit_graph.begin();
	while(it != edit_graph.end()) {
		short i = 0;
		for(Graph::const_iterator p = edit_graph.begin(); p != edit_graph.end(); ++i, ++p) 
			if(it->first != p->first && HammingDistance(WordList[it->first], WordList[p->first]) == 1) 
				it->second.push_back(i);
		it++;
	}

}

void Dijkstra(short source, short target, const Graph &graph, 
				map<short, short> &min_distance, map<short, short> &previous)
{
	const short max_weight = std::numeric_limits<short>::max();
	short i = 0;
	for(short i = 0; i < graph.size(); ++i) {
		short v = i;
		min_distance[v] = max_weight;
		for (AdjacencyList::const_iterator neighbor_iter = graph[i].second.begin();
				neighbor_iter != graph[i].second.end();
				neighbor_iter++)
		{
			short v2 = *neighbor_iter;
			min_distance[v2] = max_weight;
		}
	}
	min_distance[source] = 0;
	set<pair<short, short> > vertex_queue;
	vertex_queue.insert(make_pair(min_distance[source], source));

	while (!vertex_queue.empty()) {
		short u = vertex_queue.begin()->second;
		vertex_queue.erase(vertex_queue.begin());

		if (u == target) break;

		// Visit each edge exiting u
		const AdjacencyList &neighbors = graph[u].second;
		for (AdjacencyList::const_iterator neighbor_iter = neighbors.begin();
				neighbor_iter != neighbors.end();
				neighbor_iter++)
		{
			short v = *neighbor_iter;
			short distance_through_u = min_distance[u] + 1;
			if (distance_through_u < min_distance[v]) {
				vertex_queue.erase(make_pair(min_distance[v], v));
				min_distance[v] = distance_through_u;
				previous[v] = u;
				vertex_queue.insert(make_pair(min_distance[v], v));

			}

		}
	}
}

short shortest_path(const Graph& graph, short start, short end, list<string>& path) {
	map<short, short> min_distance;
	map<short, short> previous;
	Dijkstra(start, end, graph, min_distance, previous);

	map<short, short>::const_iterator prev;
	path.push_front(graph[end].first);
	while((prev = previous.find(end)) != previous.end()) {
		end = prev->second;
		path.push_front(graph[end].first);
	}
}


bool Doublets(string& start, const string& end, list<string>& doublets) {
	short sz = start.size();
	if(pre_computed[sz].empty() == true) 
		init_graph(pre_computed[sz], start);

	pair<short,short> index = get_index(pre_computed[sz], start, end);
	shortest_path(pre_computed[sz], index.first, index.second, doublets);
	return ( doublets.front() == start && doublets.back() == end);
}

/* main
 *  * */
int main() {
	std::ios_base::sync_with_stdio (true);
	string line;
	string start, end;
	list<string> doublets;
	while(cin.eof() != true) {
		tokens.clear();
		getline(cin, line);
		tokens << line;
		if(cin.eof() == true || (line.find_first_not_of(" \t\r") == string::npos)) break;
		//if(cin.eof() == true || (line.find_first_not_of(" \t") == string::npos)) break;
		tokens >> start;
		WordBySize.insert(WordBySize.end(), make_pair(start.size(), start));
		short pad = ((start.size() + 3) & ~0x03)-start.size();
		WordList.insert(WordList.end(), make_pair(start, start+string(pad, (char)0)));
	}
	bool entry = true;
	while(cin.eof() != true) {
		start.clear();
		end.clear();
		cin >> start >> end;
		if(start.empty() == false && end.empty() == false) {
			entry == true ? entry = false : cout << endl;
			if(start.size() != end.size() ||\
					WordList.find(start) == WordList.end() ||\
					WordList.find(end) == WordList.end()) {
				cout << no_output << endl;
			} else if( start == end) {
				cout << start << endl;
			} else {
				doublets.clear();
				if(Doublets(start, end, doublets) == true)
					copy(doublets.begin(), doublets.end(), ostream_iterator<string>(cout, "\n"));
				else
					cout << no_output << endl;
			}
		}
	}
	return 0;
}
